<?php
//+----------------------------------------------------------------------
//| ThinkPHP [ WE CAN DO IT JUST THINK IT ]
//+----------------------------------------------------------------------
//| Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
//+----------------------------------------------------------------------
//| Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
//+----------------------------------------------------------------------
//| Author: liu21st <liu21st@gmail.com>
//+----------------------------------------------------------------------
//$Id: Dispatcher.class.php 2840 2012-03-23 05:56:20Z liu21st@gmail.com $
/**
 +------------------------------------------------------------------------------
 * ThinkPHP内置的Dispatcher类
 * 完成URL解析、路由和调度
 +------------------------------------------------------------------------------
 * @category   Think
 * @package  Think
 * @subpackage  Util
 * @author    liu21st <liu21st@gmail.com>
 * @version   $Id: Dispatcher.class.php 2840 2012-03-23 05:56:20Z liu21st@gmail.com $
 * @last modify 2012-12-04 16:36:10 by mashanling
 +------------------------------------------------------------------------------
 */
class Dispatcher {

    /**
     *
     * 获得实际的操作名称
     *
     * @last modify 2012-12-04 16:36:41 by mashanling
     *
     * @access static,private
     *
     * @param string $var 变量名
     *
     * @return string 操作名称
     */
    static private function getAction($var) {
        if (empty($_GET[$var])) {
            $action = empty($_POST[$var]) ? C('DEFAULT_ACTION') : $_POST[$var];
        }
        else {
            $action = $_GET[$var];
        }

        unset($_POST[$var], $_GET[$var]);
        define('P_ACTION_NAME', $action);

        return strip_tags(C('URL_CASE_INSENSITIVE') ? strtolower($action) : $action);
    }

    /**
     *
     * 获得实际的模块名称
     *
     * @last modify 2012-12-04 16:58:51 by mashanling
     *
     * @access static,private
     *
     * @param string $var 变量名
     *
     * @return string 模块名称
     */
    static private function getModule($var) {
        $module = empty($_GET[$var]) ? C('DEFAULT_MODULE') : $_GET[$var];

        unset($_GET[$var]);

        if (C('URL_CASE_INSENSITIVE')) {//URL地址不区分大小写
            define('P_MODULE_NAME', strtolower($module));
            //智能识别方式 index.php/user_type/index/ 识别到 UserTypeAction 模块
            $module = ucfirst(parse_name(P_MODULE_NAME, 1));
        }

        return strip_tags($module);
    }

    /**
     *
     * URL映射到控制器
     *
     * @last modify 2012-12-04 16:49:32 by mashanling
     *
     * @access static,public
     *
     * @return void 无返回值
     */
    static public function dispatch() {
        $url_mode = C('URL_MODEL');

        if (!empty($_GET[$c = C('VAR_PATHINFO')])) { //判断URL里面是否有兼容模式参数
            $_SERVER['PATH_INFO'] = $_GET[$c];
            unset($_GET[$c]);
        }

        //分析PATHINFO信息
        if (IS_CLI) {
            $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
            $_SERVER['REQUEST_URI'] = $_SERVER['PATH_INFO'];
        }
        elseif (empty($_SERVER['PATH_INFO'])) {
            $types = explode(',', C('URL_PATHINFO_FETCH'));

            foreach ($types as $type) {

                if (0 === strpos($type, ':')) {//支持函数判断
                    $_SERVER['PATH_INFO'] = call_user_func(substr($type, 1));
                    break;
                }
                elseif (!empty($_SERVER[$type])) {
                    $_SERVER['PATH_INFO'] = (0 === strpos($c = $_SERVER[$type], $s = $_SERVER['SCRIPT_NAME'])) ? substr($c, $s) : $c;
                    break;
                }
            }
        }

        $depr = C('URL_PATHINFO_DEPR');

        if (!empty($_SERVER['PATH_INFO'])) {
            tag('path_info');

            if ($c = C('URL_HTML_SUFFIX')) {
                $_SERVER['PATH_INFO'] = preg_replace('/\.' . trim($c, '.') . '$/i', '', $_SERVER['PATH_INFO']);
            }

            if (!self::routerCheck()) {//检测路由规则 如果没有则按默认规则调度URL
                $paths = explode($depr, trim($_SERVER['PATH_INFO'], '/'));

                if ($c = C('VAR_URL_PARAMS')) {//直接通过$_GET['_URL_'][1] $_GET['_URL_'][2] 获取URL参数 方便不用路由时参数获取
                    $_GET[$c] = $paths;
                }

                $var = array();

                if (!isset($_GET[$c = C('VAR_MODULE')])) { //还没有定义模块名称
                    $var[$c] = array_shift($paths);
                }

                $var[C('VAR_ACTION')] = array_shift($paths);

                //解析剩余的URL参数
                preg_replace('@(\w+)' . $depr . '([^' . $depr . '\/]+)@e', '$var[\'\\1\']=strip_tags(\'\\2\');', implode($depr, $paths));
                $_GET = array_merge($var, $_GET);
            }

            define('__INFO__', $_SERVER['PATH_INFO']);
        }

        define('MODULE_NAME', self::getModule(C('VAR_MODULE')));
        define('ACTION_NAME', self::getAction(C('VAR_ACTION')));
        define('__SELF__', strip_tags($_SERVER['REQUEST_URI']));//URL常量
        //define('__APP__', strip_tags(PHP_FILE));//当前项目地址

        //当前模块和分组地址
        $module = defined('P_MODULE_NAME') ? P_MODULE_NAME : MODULE_NAME;

        if (defined('GROUP_NAME')) {
            define('__GROUP__', (!empty($domain_group) || strtolower(GROUP_NAME) == strtolower(C('DEFAULT_GROUP'))) ? __APP__ : __APP__ . '/' . GROUP_NAME);
            define('__URL__', !empty($domain_module) ? __GROUP__ . $depr : __GROUP__ . $depr . $module);
        }
        else {
            define('__URL__', !empty($domain_module) ? __APP__ . '/' : __APP__ . '/' . $module);
        }

        define('__ACTION__', __URL__ . $depr . ACTION_NAME);//当前操作地址
        $_REQUEST = array_merge($_POST, $_GET);//保证$_REQUEST正常取值
    }//end dispatch

    /**
     * 路由检测
     *
     * @last modify 2012-12-04 16:57:49 by mashanling
     *
     * @access static,public
     *
     * @return bool false
     */
    static public function routerCheck() {
        return false;
    }
}